當我們今天有了很多功能後,有時候會希望某些功能可以進入遊戲後再做調整,例如:
這些功能如果可以透過一個設定檔(Configuration)來控制,只要調整檔案內對應的欄位值,儲存後就可以即時在遊戲內看到調整後的結果,而不用像我們現在的做法:
停止遊戲 -> 改程式碼 -> 儲存後,重新進入遊戲 -> 看結果
看起來似乎簡單許多,不是嗎?
com.ithome.mymod.configs
套件目錄下(若沒有請自行建立),新增一個CustomConfig
類別:net.minecraftforge.common.config.Configuration
這個類別開始。我們在CustoConfig
這個類別內建立全域變數configuration
,並且定義三個基本方法:init()
, loadConfiguration()
與getConfiguration
package com.ithome.mymod.configs;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
public class CustomConfig {
public static Configuration configuration;
// 初始化設定檔
public static void init(FMLPreInitializationEvent event) {
}
// 讀取設定檔
private static void loadConfiguration() {
}
// 取得Configuration物件
public static Configuration getConfiguration() {
}
}
init()
方法用的參數是FMLPreInitializationEvent
事件,表示這個方法之後會在FMLPreInitializationEvent
事件中呼叫。然後我們填入初始化configuration
的內容,把我們的設定檔路徑設定為config/mymod.cfg
:
// 初始化設定檔
public static void init(FMLPreInitializationEvent event) {
String configDir = event.getModConfigurationDirectory().toString();
if(configuration == null) {
File path = new File(configDir + "/" + Constants.MOD_ID + ".cfg");
configuration = new Configuration(path);
loadConfiguration();
}
}
Configuration
有兩個重要的動作:
loadConfiguration
內,作為一個完整的檔案讀取寫入:// 讀取設定檔
private static void loadConfiguration() {
configuration.load();
// 當設定檔有變更,才做儲存
if(configuration.hasChanged()) {
configuration.save();
}
}
getConfiguration
回傳我們的configuration
物件:
// 取得Configuration物件
public static Configuration getConfiguration() {
return configuration;
}
開啟MyMod
主程式,在preInit()
內初始化我們在前一步驟建立的設定檔類別:
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
...(略)
CustomConfig.init(event);
...(略)
}
到目前為止我們只把設定檔的功能打開,但並不能從畫面中更改設定。要使用這個功能,我們需要再新增兩個檔案到com.ithome.mymod.configs
套件目錄下:
CustomGuiFactory.java
package com.ithome.mymod.configs;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.IModGuiFactory;
import java.util.Set;
public class CustomGuiFactory implements IModGuiFactory {
@Override
public void initialize(Minecraft minecraftInstance) {
}
@Override
public Class<? extends GuiScreen> mainConfigGuiClass() {
return CustomGuiConfig.class;
}
@Override
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
return null;
}
@Override
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) {
return null;
}
}
這個檔案是用來定義我們模組自己使用的GUI設定畫面;由於需要把現有的GUI畫面整個覆蓋,這裡我們直接實作IModGuiFactory
。唯一我們需要更改的方法,是mainConfigGuiClass()
這一個,並且將它指定到我們下一步驟的檔案類別上。
CustomGuiConfig.java
package com.ithome.mymod.configs;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.client.config.GuiConfig;
public class CustomGuiConfig extends GuiConfig {
public CustomGuiConfig(GuiScreen parentScreen) {
super(parentScreen,
new ConfigElement(CustomConfig.getConfiguration().getCategory(Configuration.CATEGORY_GENERAL)).getChildElements(),
Constants.MOD_ID,
false,
false,
"This is My Mod Configuration");
titleLine2 = CustomConfig.getConfiguration().getConfigFile().getAbsolutePath();
}
}
這個類別比較特殊,需要繼承GuiConfig
這個基礎類別,並且實作建構子(Constructor)方法:
pareantScreen
作為我們GUI的母畫面。CustomConfig
包含的所有ConfigElement
物件。false
這裡我們另外指定副標題titleLine2
是我們的檔案路徑,這樣比較清楚。
回到主程式MyMod
內,在標註@Mod
加上guiFactory的連結,並且在Constants
內加入我們CustomGuiFactory
的完整類別路徑:
MyMod.java
@Mod(modid = Constants.MOD_ID, name = Constants.MOD_NAME, version = Constants.VERSION, guiFactory = Constants.GUI_FACTORY_CLASS)
public class MyMod {
...(略)
Constants.java
// gui config
public static final String GUI_FACTORY_CLASS = "com.ithome.mymod.configs.CustomGuiFactory";
好了,讓我們來建立一個參數測試看看。回到CustomConfig
類別,在最上面建立兩個測試參數:
loadConfiguration()
內透過get()
取得參數,並且設定初始值。最後的程式碼長這樣:
package com.ithome.mymod.configs;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import java.io.File;
public class CustomConfig {
public static Configuration configuration;
private static boolean updateCheck = true;
private static String greeting = null;
// 初始化設定檔
public static void init(FMLPreInitializationEvent event) {
String configDir = event.getModConfigurationDirectory().toString();
if(configuration == null) {
File path = new File(configDir + "/" + Constants.MOD_ID + ".cfg");
configuration = new Configuration(path);
loadConfiguration();
}
}
// 讀取設定檔
private static void loadConfiguration() {
configuration.load();
configuration.getBoolean("Check for Update", Configuration.CATEGORY_GENERAL, true, "Allow to check for updates");
configuration.getString("Greeting", Configuration.CATEGORY_GENERAL, "Hello sam", "Greeting to someone");
// 當設定檔有變更,才做儲存
if(configuration.hasChanged()) {
configuration.save();
}
}
// 取得Configuration物件
public static Configuration getConfiguration() {
return configuration;
}
}
# Configuration file
general {
# Allow to check for updates [default: true]
B:"Check for Update"=true
# Greeting to someone [default: Hello sam]
S:Greeting=Hello sam
}
內容我想很清楚不用多闡述,這樣我們就完成很陽春的設定檔了!
明天我們會將變更卻無法儲存的功能加進來。